#ifndef _CENTERBANK_CENTERBANKMGR_H
#define _CENTERBANK_CENTERBANKMGR_H

#include "Common.h"
#include "String.h"
#include "Resource.h"
#include "Singleton.h"
#include "json/json.h"
#include "Database/Field.h"

#include "GameDefine.h"
#include XMLDATA_MGR_PATH

// 默认安全密码
#define DEFAULT_PASSWORLD	"21218cca77804d2ba1922c33e0151105"

class UserPtr;
class WorldPacket;
struct game_bank_tag_;
typedef struct game_bank_tag_ GameBank;
struct HappyFarm;
// 银行操作
enum Operate
{
	en_Operate_Error = 0, // 错误
	en_Operate_Save = 1, // 存
	en_Operate_Get = 2, // 取
	en_Operate_Buff = 3,	// 数据中转
	en_Operate_GatewayAdd = 4, // 网关操作增加
	en_Operate_GatewayReduce = 5, // 网关操作减少
	en_Operate_PublicItem = 6,	// 操作公共数据
	en_Operate_HappyFarm = 7,	// 开心牧场
	en_Operate_HappyFarmNew = 8,// 开心牧场（新版）
	en_Operate_GiveItem = 9,	// 赠送道具
};
//乐码操作类型
enum LeMaOperotorMode
{
	en_LMOM_Create 	= 1,		//创建
	en_LMOM_Check 	= 2,		//验证
	en_LMOM_Use 	= 3,		//使用
	en_LMOM_TimeOver = 4,		//过期
};

// 物品ID
enum ItemModelId
{
	en_ItemModelId_Coins 	= 1000,	// 铜钱
	en_ItemModelId_Match 	= 1001,	// 参赛券
	en_ItemModelId_Exchange = 1002, // 兑换券
	en_ItemModelId_RRQ 		= 1003,	// 人人券
	en_ItemModelId_Gold 	= 1005, // 游戏代币			
	en_ItemModelId_Bugle	= 1010,	// 喇叭
	en_ItemModelId_Mammon 	= 1011,	// 财神卡I
	en_ItemModelId_Mammon2 	= 1012,	// 财神卡II	
	en_ItemModelId_Diamond	= 1013,	// 钻石卡I
	en_ItemModelId_Diamond2	= 1014,	// 钻石卡II
	en_ItemModelId_Luck		= 1016,	// 幸运卡I
	en_ItemModelId_Luck2	= 1017,	// 幸运卡II
	en_ItemModelId_Luck3	= 1018,	// 幸运卡III
	en_ItemModelId_Subsidy	= 1019,	// 救济卡
	en_ItemModelId_Token 	= 1020,	// 乐币
	en_ItemModelId_Score 	= 1021,	// 积分
	en_ItemModelId_BuQianKa = 1022,	// 签到卡
	en_ItemModelId_GoldTicket = 1023,	// 金券
	en_ItemModelId_DiamondOpen = 1024,	// 开局费钻石
	en_ItemModelId_Money	= 1050,	// 元宝
};


/** @中转数据定义@ 
 * data1:铜钱
 * data2:兑换券
 * data3:代币
 * data4:参赛券 
 * data5:形象ID 
 * item1:元宝
 * item2:乐币
 * item3:积分
 * item4:补签卡
 * item11:喇叭
 * item12:财神卡I
 * item13:财神卡II
 * item14:钻石卡I
 * item15:钻石卡II 
 * item17:幸运卡I
 * item18:幸运卡II
 * item19:幸运卡III
 * item20:救济卡
 */

typedef struct _field_name
{
	uint32 modelid;
	String field;
	
	_field_name(void):modelid(0),field(""){};
}FieldName;
typedef std::list<FieldName>	FieldNameList;

struct BankPublicData
{
	uint32 	Silver;	// 银转盘
	uint32  Gold;	// 金转盘
	uint32 	FirstBuy;	// 首充标记
	uint32 	FirstBuyTimer;// 首充时间
	uint32 	GetLemaTime;// 乐码领取时间
	uint32  Token;	// 乐币
	uint32 	Score;	// 积分
	void Init()
	{
		Silver = 0;
		Gold = 0;
		FirstBuy = 0;
		FirstBuyTimer = 0;
		GetLemaTime = 0;
		Token = 0;
		Score = 0;
	}
	BankPublicData()
	{
		Init();
	}
};
// 月签到信息
struct SigninStruct
{
	uint32 month;
	std::map<uint32, bool> mapDays;
	uint32 day5;	// 连续签到5日
	uint32 day10;
	uint32 day15;
	uint32 day20;
	uint32 dayAll;
	uint32 total5;	// 累计签到5日
	uint32 total15;
	uint32 total25;
	SigninStruct()
	{
		Init();
	}	
	void Init()
	{
		month = 0;
		mapDays.clear();
		day5 = 0;
		day10 = 0;
		day15 = 0;
		day20 = 0;
		dayAll = 0;
		total5 = 0;
		total15 = 0;
		total25 = 0;
	}
};

// 牲畜实例结构
struct HappyFarmItem
{
	uint32 id;
	uint32 model_id;
	uint32 begin_time;
	uint32 end_time;
	void Init()
	{
		id = 0;
		model_id = 0;
		begin_time = 0;
		end_time = 0;
	}
	HappyFarmItem()
	{
		Init();
	}
};

enum enSignStatus
{
	enSignStatus_NotGet = 0,		// 未领
	enSignStatus_CanGet = 1,		// 可领
	enSignStatus_Get = 2,			// 已领
};

struct stCommonSingleSignResult
{
	stCommonSingleSignInfo stCSS;	// 签到信息
	uint32 status;					// 签到状态
	
	stCommonSingleSignResult()
	{
		Init();
	}
	
	void Init()
	{
		stCSS.Init();
		status = 0;
	}
};

struct stCommonSign
{
	uint32 agent_id;			// 代理商ID
	uint32 gz_id;				// 分区ID
	uint32 sign_mode;			// 签到模式（1 周签到 2 月签到）
	uint32 sign_sub_mode;		// 签到子类型（1 固定签到奖励 2 连续签到奖励）
	uint32 update_combo_mode;	// 签到更新模式（1 周更新 2 月更新）
	uint32 update_bounty_mode;	// 奖励更新模式(1 周更新 2 月更新)
	uint32 last_updateTime;		// 上一次签到更新时间
	uint32 combo_days;			// 连签天数
	uint32 count_days;			// 累签天数
	uint32 last_updateComboTime;	// 最后一次更新连签信息时间
	
	String agent_name;			// 代理商名称
	
	std::vector<stCommonSingleSignResult>	vSignInfo;		// 基础签到
	std::vector<stCommonSingleSignResult>	vComboInfo;		// 连签信息
	std::vector<stCommonSingleSignResult>	vCountInfo;		// 累签信息
	
	stCommonSign()
	{
		Init();
	}
	
	void Init()
	{
		agent_id = 0;
		gz_id = 0;
		sign_mode = 0;
		sign_sub_mode = 0;
		update_combo_mode = 0;
		update_bounty_mode = 0;
		last_updateTime = 0;
		combo_days = 0;
		count_days = 0;
		last_updateComboTime = 0;
		
		agent_name = "";
		
		vSignInfo.clear();
		vComboInfo.clear();
		vCountInfo.clear();
	}
};

#define WGS_HAPPY_FARM_INNER_MUTEX_NAME HAPPY_FARM_inner_mutex
#define WGS_HAPPY_FARM_INNER_MUTEX mutable boost::mutex WGS_HAPPY_FARM_INNER_MUTEX_NAME;
#define WGS_HAPPY_FARM_INNER_LOCK		boost::lock_guard<boost::mutex> wgsHAPPY_FARMInnerMutexLock(WGS_HAPPY_FARM_INNER_MUTEX_NAME);

#define WGS_DATABUFF_INNER_MUTEX_NAME databuff_inner_mutex
#define WGS_DATABUFF_INNER_MUTEX mutable boost::mutex WGS_DATABUFF_INNER_MUTEX_NAME;
#define WGS_DATABUFF_INNER_LOCK		boost::lock_guard<boost::mutex> wgs_databuff_InnerMutexLock(WGS_DATABUFF_INNER_MUTEX_NAME);

#define WGS_ZUJUTRACK_MUTEX_NAME zujutrack_mutex
#define WGS_ZUJUTRACK_MUTEX mutable boost::mutex WGS_ZUJUTRACK_MUTEX_NAME;
#define WGS_ZUJUTRACK_LOCK		boost::lock_guard<boost::mutex> wgs_zujuTrackMutexLock(WGS_ZUJUTRACK_MUTEX_NAME);


// 银行管理
class CenterBankManager : public Singleton<CenterBankManager>
{
public:
	// 银行状态
	enum BankStatus
	{
		BankStatusFree	= 1,			// 正常数据
		BankStatusStart = 3,			// 准备数据进入游戏
		BankStatusStartData = 4,		// 进入游戏写银行数据 (中间处理状态)
		BankStatusPrep = 5,				// 游戏数据准备完毕
		
		BankStatusLoging = 6,			// 进入游戏正在取出数据
		BankStatusLogined = 7,			// 进入游戏完毕
		
		BankStatusLogouting = 8,		// 返回大厅前准备数据
		BankStatusLogoutData= 9,		// 返回大厅写银行数据 (中间处理状态)
		BankStatusLogouted = 2,			// 返回大厅的数据准备完毕
		BankStatusCompose = 10,			// 正拷贝出数据	
	};

	// 银行物品标志
	enum BankItemFlag
	{
		BankItemFree = 0,		// 正常
		BankItemPrep = 1,		// 待写
	};
	
public:
	WGS_HAPPY_FARM_INNER_MUTEX
	WGS_DATABUFF_INNER_MUTEX
	WGS_ZUJUTRACK_MUTEX
	CenterBankManager();
	~CenterBankManager();
	
	// 更新银行数据
	bool UpdateCenterBank(Fields * fields, const char * QueryString, ...);
	
	// 获取银行存款
	uint64 GetCenterBankWealth(CharPtr &pChr, const uint32 modelId);
	uint64 GetCenterBankWealth(UserPtr &pUser, const uint32 modelId);
	// 存钱
	bool SaveWealthInBank(UserPtr &pUser, const uint32 modelId, const uint32 num, const uint8 & optype = en_Operate_Save);
	// 取钱
	bool GetWealthFromBank(UserPtr &pUser, const uint32 modelId, const uint32 num, const uint8 & optype = en_Operate_Get);
	// 获取银行信息
	bool GetRealBank(UserPtr &pUser, GameBank &bank); 
	uint8 GetRealBank(const uint32 & pid, GameBank &bank); 
	// 添加
	uint64 AddBankInfo(UserPtr &pUser, GameBank *pGameBank = NULL); 
	// 绑定银行
	bool BandFatherBank(UserPtr &pUser, const uint32 platformId);
	// 设置安全密码
	bool SetPassworld(UserPtr & pUser, const String & pwd);
	// 获取安全密码
	String GetPassworld(UserPtr & pUser);
	// 重置安全密码
	void ResetPassworld(UserPtr & pUser);
	// 登陆设置安全密码
	void CopyPassworld(UserPtr & pUser);
	// 是否存在银行
	bool ExistBank(UserPtr & pUser);
	// 用户登录
	void UserLogin(UserPtr &pUser);
	// 获取银行表USER_DATA字段值(Json)
	uint32 GetUserDataVal(const GameBank &pBank, const String &strKey);
	String GetUserDataString(const GameBank &pBank, const String &strKey);
	Json::Value GetUserDataJson(const GameBank &pBank, const String &strKey);
	// 设置银行表USER_DATA字段值(Json)
	void SetUserDataVal(GameBank &pBank, const String &strKey, const uint32 &val);
	void SetUserDataString(GameBank &pBank, const String &strKey, const String &val);
	void SetUserDataJson(GameBank &pBank, const String &strKey, const Json::Value &val);
	// 保存USERDATA到数据库
	void SaveUserDataDB(const GameBank &pBank);
public:
	/** @公共数据操作@	
	 @data1:银转盘
	 @data2:金转盘
	 @data3:首充标记
	 @data4:首充时间
	 @data5:罗马领取时间
	**/
	uint32 	AddPublicData(UserPtr &pUser, const uint32 &pd_type, const uint32 &number, const uint32 &cause = 0);
	bool 	ReducePublicData(UserPtr &pUser, const uint32 &pd_type, const uint32 &number, const uint32 &cause = 0);
	void 	SetPublicData(UserPtr &pUser, const uint32 &pd_type, const uint32 & number);
	void	GetPublicData(UserPtr &pUser, GameBank *pBank);
	bool	GetPublicData(const uint32 &platformId, GameBank *pBank);
	uint32 	GetPublicData(UserPtr &pUser, const uint32 &pd_type);
	// 设置公共配置
	void 	SetPublicConfig(UserPtr &pUser, String strConfig);
	// 获取所有公共数据
	bool 	GetPublicData(UserPtr &pUser, BankPublicData *st);
	// 获取用户原始GZID
	uint32  GetGameGZID(UserPtr &pUser);
	// 银行自动取款
	void GetUserBankCoinsBySystem(UserPtr & pUser);
public:	
	/*************** 关于签到系统 *****************/
	// 签到并领取
	bool 	GetOrSignin(UserPtr &pUser, const uint32 &opType, const uint32 &data1);
	// 结构体转Json
	String 	SigninOfStructToJson(SigninStruct &ss);
	// Json转结构
	bool 	SigninOfJsonToStruct(const String &szJson, SigninStruct *pSign);
	// 通知签到信息
	// bool 	CreateSigninInfoPacket(WorldPacket *packet, UserPtr &pUser);
	bool 	CreateSigninInfoPacket(WorldPacket *packet, UserPtr &pUser, SigninStruct &ss, bool isFirstLogin);
	// 领取反馈
	bool 	CreateSigninResultPacket(WorldPacket *packet, const uint8 &opType, const uint8 &data1, const uint32 &coinsNum = 0);
	
	//===========================公共签到===================================
	// 初始签到信息
	bool InitCommonSign(UserPtr & pUser);
	// 公共签到 type 1 日签 2 连签 3 累签 4 补签
	bool GetCommonSign(UserPtr & pUser, const uint32 & type, const uint32 & data);
	// 公共签到结构体转JSON
	Json::Value CommonSignStructToJson(stCommonSign & cs);
	// JSON转公共签到结构体
	bool JsonToCommonSignStruct(const Json::Value & valJson, stCommonSign & cs);
	
	
	//===========================公共签名===================================
	bool CommonSignName(CharPtr & pChr, const uint32 & platform_id, String & content);
	bool GetCommonSignName(CharPtr & pChr, const uint32 & platform_id);
	
	/*************** 关于开心牧场 *****************/
	// 结构体与Json互转
	void 	HappyFarmJsonToStruct(const String &strJson, std::list<HappyFarmItem> *pList);
	String 	HappyFarmStructToJson(std::list<HappyFarmItem> &lstHappyFarm);
	void 	SaveHappyFarmDB(const GameBank &bank);
	// 购买或出售
	void 	HappyFarmBusiness(UserPtr &pUser, const uint32 &opType, const uint32 &farmId, const uint32 &number = 0);
	// 将牧场动物列表转换为map结构
	void 	UpdateFramTransLog(CharPtr & pChr,const uint8 & sub_type,const uint8 & op_type,
									const uint32 & model_id,const uint32 & num,
									std::list<HappyFarmItem> farms,const uint32 & destPId = 0); 
	// 增加或减少牧场动物
	void 	OperatorBusinedd(UserPtr &pUser, const uint32 &opType,const uint32 &farmId, const uint32 &number = 0);
	// 赠送
	bool 	HappyFarmGiving(UserPtr &pUser, const uint32 &destPId, const uint32 &farmId);
	// 创建我的牧场数据包
	bool 	CreateMyHappyFarmPacket(WorldPacket *packet, std::list<HappyFarmItem> &pList);
	// 创建买卖动物数据包
	bool 	CreateBusinessHappyFarmPacket(WorldPacket *packet, uint8 result, uint8 type, const uint32 &farmId, const String &strName, uint16 number, uint32 getCoins);
	// 创建赠送动物数据包
	bool 	CreateGivingHappyFarmPacket(WorldPacket *packet, uint8 result, uint32 farmId, uint32 destPId, String strNick);
	// 创建赠送记录数据包
	bool 	CreateGivingRecodePacket(WorldPacket *packet, uint32 platformId);
	// 创建可购买动物列表
	bool 	CreateBuyFarmListPacket(WorldPacket *packet);
	// 创建单动物更新包
	bool 	CreateSingleFarmPacket(WorldPacket *packet, const HappyFarmItem &hfi);
	// 牧场日志
	bool 	HappyFarmLog(const uint32 &src_id, const String &src_nick, const uint32 &dest_id, const String &dest_nick,
					const uint32 &farmModelId, const String &szName, const uint32 &number, const uint32 &coins);
	// 出售全部动物
	void 	SellAllFarm(UserPtr & pUser);
	
	/********************组局行踪相关******************/
	// 更新组局行踪数据
	void UpdateZujuTrackInfo(CharPtr & pChr, const uint32 & cb_id, const uint32 & game_id, const uint32 & gz_id, String join_code);
	// 清空组局行踪数据
	void CancelZujuTrackInfo(CharPtr & pChr);
	// 获取组局行踪数据
	void GetZujuTrackInfo(CharPtr & pChr);
	// 保存组局行踪数据
	void SaveZujuTrackInfo(GameBank & pBank);
	// 组局行踪信息
	bool CreateZujuTrackInfoPacket(WorldPacket *packet, 
									const uint32 & cb_id, 
									const uint32 & game_id, 
									const uint32 & gz_id,
									String join_code,
									bool bPlaying = false);
	
protected:
	bool updatePublicDataDB(const uint32 &bankid, const String &field, const uint32 &number);
	void updatePublicDataLog(UserPtr &pUser, const uint32 &operate, const uint32 &pd_type, 
					const uint32 &upNum, const uint32 &currNum, const uint32 &cause = 0);
	
	bool isChangeTestUser(CharPtr &pChr);
public:	
	/*************** 中转数据相关 *****************/
	// 游戏服务器 返回：TRUE跳转,FALSE不跳转
	bool 	JoinGameServer(UserPtr & pUser,  const uint16 & thegid, uint16 *currgid = NULL);
	// 
	bool 	LeaveGameServer(UserPtr & pUser, const uint16 & thegid, const uint16 & destid = 0);
	bool 	DisconnectServer(UserPtr & pUser, const uint16 & mygid = 0);
	// 重置游戏跳转状态
	void 	ResetGameExchage(UserPtr & pUser);	
	
	// 重新加载游戏数据字段配置
	void 	ReloadFieldXML(void);
	// 更新中转数据
	bool 	UpdateBankBuffDB(const GameBank & bank, const uint32 &laststatus);
	// 修改银行状态
	bool 	updateBankStatusDB(GameBank & bank, const uint8 & nextstatus, const uint8 & backstatus);	
	// 修改GZID
	void 	updateBankGzidDB(GameBank & bank);
	/**
	 * @创建时间 2012-07-05
	 * @创建人 StarX
	 * @函数作用 游戏服操作结果 0x0014
	 * @参数
	 *  @result 操作结果
	 *  @gameid GAMEID
	 */
	bool 	CreateOpServerResult(WorldPacket * packet,const uint8 & type,  const uint8 & result, const uint16 & gameid);
	
	bool 	CreateExitGameResult(WorldPacket *packet, uint8 result, uint32 gzid);
	bool 	CreateExitGameResultEx(WorldPacket *packet, uint8 result, uint32 gzid);

	// 存取款银行日志
	void SaveAndGetWealthLog(UserPtr &pUser, const uint32 operate, const uint32 modelId, const uint32 num, const uint32 curNum);
	// 玩家行踪日志
	void WhereaboutsLog(UserPtr &pUser, const uint8 & type, const uint8 & where, const GameBank * pBank);
		
	// 加载各个游戏通用数据字段配置
	void 	LoadFieldXml(void);	
	const String *GetFieldName(const uint16 & gid, const uint32 & modelid);
	bool 	IsGameExist(const uint32 & gid);
	
	bool 	GetItemNum(CharPtr & pChr, const uint32 & modelid, uint32 * num);
	uint32 	GetBankSafeItemNum(GameBank & bank, const uint32 & modelid);	
	bool 	GetSafeItemNum(CharPtr & pChr, const uint32 & modelid, uint32 * num);	
	
	void 	SetBankSafeItemNum(GameBank & bank, const uint32 & modelid, const uint32 & num);	
	bool 	SetSafeItemNum(const uint16 & thegid, CharPtr & pChr, const uint32 & modelid, const uint32 & num);
	void 	SetItemNum(const uint16 & thegid, CharPtr & pChr, const uint32 & modelid, const uint32 & num);
	bool 	SetSafeItemFlag(CharPtr & pChr, const uint32 & modelid);	
	
	void 	addItemNum(const uint16 & thegid, CharPtr & pChr, const uint32 & modelid, const uint32 & num);
	void 	addSafeItemNum(const uint16 & thegid, CharPtr & pChr, const uint32 & modelid, const uint32 & num);
	bool 	resetSafeItemNum(const uint16 & thegid, CharPtr & pChr, const uint32 & modelid, const uint32 & num);
	bool 	restoreSafeItemNum(const uint16 & thegid, CharPtr & pChr, const uint32 & modelid);
	
	bool 	InputBankBuffer(CharPtr & pChr, const uint32 & thissid, GameBank & bank, const uint8 & status, const bool & safe = false );
	bool 	OutputBankBuffer(CharPtr & pChr, const uint32 & thissid, GameBank & bank, const uint8 & status, const bool & safe = false);
	
	void 	SetBankDataFlag(CharPtr & pChr);
	
	void 	restoreDataFlag(const uint16 & theid, CharPtr & pChr);
	bool 	CreateItem(CharPtr & container, const uint32 & model_id, const uint32 & num);
	
	/**
	 * @创建时间 2013-11-25
	 * @创建人 Roach
	 * @函数作用 乐码日志
	 * @参数
	 *  @pid 用户游戏ID
	 *  @mode 操作模式( 1 创建 2 验证 3 使用 4 过期）
	 *  @exchange_id 乐码ID
	 *  @data1  附加数据1
	 */
	 void LeMaOpLog(const uint32 & pid,const uint8 & mode,const uint32 & exchange_id,const uint32 & data1 = 0);
	
	/**
	 * @创建时间 	2016-05-23
	 * @创建人 		Roach
	 * @函数租用 	更新牧场动物变化日志
	 * @参数
	 *  @pChr 		角色Ptr
	 *  @op_type	操作类型（1 加 2 减）
	 *  @model_id	动物模式ID
	 *  @mapFarms	当前动物库存数量
	 */
	void UpdateFarmInfoLog(CharPtr & pChr,const uint8 & sub_type,const uint8 & op_type, 
										const uint32 & model_id,const uint8 & num,
										std::map<uint32,uint32> mapFarms,const uint32 & destPId = 0);
	
	// 更新宠物库存数量
	void UpdateFarmNumber(CharPtr & pChr,std::map<uint32,uint32> mapFarms);
	
private:
	// 字段配置
	std::map<uint16, FieldNameList>	m_mapFieldName;
	
};

#define		sBankMgr			CenterBankManager::getSingleton()
#endif // _28_CENTERBANKMGR_H
